#include "utils/utils.h"
#include "utils/string_util.h"
#include "logger.h"
#include <spawn.h>
#include <fcntl.h>
#include <unistd.h>
#include <filesystem>

extern char **environ;  // 声明外部环境变量数组

Utils::Utils()
{}
std::string Utils::formatElement(const tinyxml2::XMLElement *element)
{
    tinyxml2::XMLPrinter printer;
    element->Accept(&printer);
    return printer.CStr();
}
ResultDesc Utils::createProcess(pid_t *pid, const std::string &process, const std::string &argv, bool printScreen)
{
    std::vector<std::string> env_strings;
    for (char **env = environ; *env; ++env)
    {
        env_strings.emplace_back(*env);
    }
    return createProcess(pid, process, argv, env_strings, printScreen);
}

ResultDesc Utils::createProcess(pid_t *pid, const std::string &process, const std::string &argv, const std::vector<std::string>& env_strings, bool printScreen)
{
    ROS_INFO("current environ: %s", *environ);

    std::vector<std::string> split = utils::StringUtil::split(argv, " ", utils::SkipEmptyParts);
    //args
    std::vector<char *> args;
    args.push_back(const_cast<char *>(process.c_str()));
    for (const auto &cmd: split)
    {
        args.push_back(const_cast<char *>(cmd.c_str()));
    }
    args.push_back(nullptr);
    //env
    std::vector<char *> env_ptrs;
    for(int i = 0; i < env_strings.size(); ++i)
    {
        env_ptrs.push_back(const_cast<char *>(env_strings.at(i).c_str()));
    }
    // 添加终止符（必须为 nullptr）
    env_ptrs.push_back(nullptr);

    ROS_INFO("exec: %s %s", process.c_str(), argv.c_str());
    posix_spawn_file_actions_t actions;
    posix_spawn_file_actions_init(&actions);
    if (!printScreen)
    {
        posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO, "/dev/null", O_WRONLY | O_CREAT | O_APPEND, 0);//重定向 stdout (1) 到 /dev/null
        posix_spawn_file_actions_addopen(&actions, STDERR_FILENO, "/log/roslaunch/stderr.log", O_WRONLY | O_CREAT | O_APPEND, 0);
    }
    int status = posix_spawn(pid, process.c_str(), &actions, nullptr, args.data(), env_ptrs.data());
    posix_spawn_file_actions_destroy(&actions);

    char buf[256] = {0x00};
    char *msg = strerror_r(ENOENT, buf, sizeof(buf));

    return {status, msg};
}
bool Utils::isBool(const std::string &str)
{
    return str == "true" || str == "false";
}
bool Utils::isInt(const std::string &str)
{
    if (str.empty()) return false;

    size_t i = 0;
    // 处理符号
    if (str[0] == '+' || str[0] == '-') i++;

    // 检查是否全是数字
    if (i == str.size()) return false;  // 只有符号
    for (; i < str.size(); i++)
    {
        if (!std::isdigit(str[i]))
            return false;
    }
    return true;
}
bool Utils::isDouble(const std::string &str)
{
    if (str.empty()) return false;

    size_t i = 0;
    bool hasDot = false;

    // 处理符号
    if (str[0] == '+' || str[0] == '-') i++;

    // 检查是否有非法字符，并处理小数点
    if (i == str.size()) return false;  // 只有符号
    for (; i < str.size(); i++)
    {
        if (str[i] == '.')
        {
            if (hasDot) return false;  // 多个小数点
            hasDot = true;
        }
        else if (!std::isdigit(str[i]))
        {
            return false;  // 非数字、非符号、非小数点字符
        }
    }

    // 确保至少有一个数字，且有小数点
    bool hasDigit = false;
    for (char c: str)
    {
        if (std::isdigit(c))
        {
            hasDigit = true;
            break;
        }
    }
    return hasDigit && hasDot;
}
bool Utils::isRelease()
{
    std::filesystem::path path("/userdata/debug");
    return !std::filesystem::exists(path);
}
std::string Utils::getLastComponent(const std::string &path)
{
    std::filesystem::path p(path);
    return p.filename().string();
}
